package scenetracer;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.rmi.RemoteException;

import javax.imageio.ImageIO;

import scenetracer.core.Scene;
import scenetracer.core.parser.Timer;
import scenetracer.rmi.Client;
import scenetracer.rmi.Master;
import scenetracer.util.Octree;

public class RunSceneTracer {

	public ArgumentsLineParser cmd = null;
	public SceneTracerOptions rtOptions = null;
	private static final int MAXPRIM = 30; 

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		RunSceneTracer runRT = new RunSceneTracer();

		runRT.cmd = new ArgumentsLineParser();
		if((runRT.rtOptions = runRT.cmd.validateArguments(args))==null)
		{
			System.out.println(runRT.cmd.getError());
			System.exit(1);
		}
			
		
		
		if(runRT.rtOptions.isClient()) {
			
           String masterArgs[] = new String[args.length-2];
           for(int i=2; i<args.length; i++)
        	   masterArgs[i-2]=args[i];
           
			new Client(runRT.rtOptions.getAddress(), runRT.rtOptions.getPort(), masterArgs);
			return;
		}
		if(runRT.rtOptions.isMaster()) {
			try {
				Master master = new Master(runRT.rtOptions.getPort());
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return;
		}
		
		//System.out.println(runRT.rtOptions.getAddress()+" "+runRT.rtOptions.getPort());

		if (runRT.rtOptions != null) {
			runRT.executeRenderer();
		}
		else
			System.err.println(runRT.cmd.getError());

	}

	private Scene loadScene() {
		Scene scene = new Scene();

		if (rtOptions.isPenumbraEnabled()) 
			scene.setPenumbra(rtOptions.getPenumbraLimit()); 


		scene.parse(rtOptions.getFileInput(), scene.getPenumbra());

		return scene;
	}

	public void executeRenderer() {

		Scene scene = null;
		Timer timer = null;
		int iterations = 1;
		Octree octree = new Octree();
		BufferedImage outputImage = null;
		
		scene = loadScene();
		SceneTracer st = new SceneTracer();
		

		if (rtOptions.isShowProgress())
			st.setShowProgress(true);

		if (rtOptions.isTimerEnabled() || rtOptions.isBenchmarkEnabled()) {
			timer = new Timer();
			timer.start();
		}

		if (rtOptions.isBenchmarkEnabled())
			iterations = rtOptions.getBenchmark();

		// System.out.println(iterations);
		scene = getOctTree(scene,octree, MAXPRIM);
		
		for (int i = 0; i < iterations; i++) {
			outputImage = st.render(scene, rtOptions.getNumThreads());
		}

		if (rtOptions.isTimerEnabled() || rtOptions.isBenchmarkEnabled()) {
			timer.end();
			Double sec = timer.seconds();
			if ((sec.doubleValue() - (double) (sec.intValue())) > 0.5)
				sec = sec + 1.0;

			System.out.println("Proceso terminado en: " + sec.floatValue()
					+" segundos");
			if (rtOptions.isBenchmarkEnabled()) {
				Double avg = sec / iterations;
				System.out.println("Tiempo promedio por render:"
						+ avg.intValue() + " segundos");
			}
		}
		System.out.println("Generando salida:" + rtOptions.getFileOutput());

		if (rtOptions.isShowResult() && outputImage != null) {
			Viewer.view(outputImage);
		}

		File file = new File(rtOptions.getFileOutput());

		try {
			ImageIO.write(outputImage, "png", file);
		} catch (IOException e) {
			
			System.exit(1);
		}

	}
	
	private static Scene getOctTree(Scene scene, Octree octTree,int maxPrim) {
		try 
		{
			scene = octTree.makeOctree(scene, maxPrim);
		} catch (StackOverflowError e) {
			scene = getOctTree(scene, octTree, maxPrim+MAXPRIM);
		}
	
		return scene;
	}
}
